package great.project.controller;

import great.project.mapper.UserInfoMapper;
import great.project.pojo.UserInfo;
import great.project.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 使用编程式事务和CountDownLunch解决多线程事务问题
 */
@RestController
@Slf4j
public class TestController {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;
    @RequestMapping("/upload/{num}")
    public String insert(@PathVariable long num) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
//        insertData(num);
        test1(num);
        stopWatch.stop();
        log.info("执行时间：{}", stopWatch.getTotalTimeSeconds());
        return stopWatch.getTotalTimeMillis() + "";
    }
    @RequestMapping("/transaction/test")
    public String testTransaction() {
        userInfoService.test1();
        ArrayList<String> list = new ArrayList<>();
        list.forEach(System.out::println);
        return "success";
    }

    private void insertData(long num) {
        List<UserInfo> list = new ArrayList<>();
        for (long i = 0; i < num; i++) {
            list.add(new UserInfo(i, i + ""));
        }
        userInfoMapper.insert(list);
    }

    //是否可以提交
    public static volatile boolean IS_OK = true;



    public void test1(long num) {
        //子线程等待主线程通知
        CountDownLatch mainMonitor = new CountDownLatch(1);
        int threadCount = 5;
        CountDownLatch childMonitor = new CountDownLatch(threadCount);
        //子线程运行结果
        List<Boolean> childResponse = new ArrayList<>();
        ExecutorService executor = Executors.newCachedThreadPool();
        long thisNum = num / threadCount;
        for (int i = 0; i < threadCount; i++) {
            int finalI = i;
            executor.execute(() -> {
                TransactionStatus transactionStatus = null;
                try {
                    transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
                    System.out.println(Thread.currentThread().getName() + "：开始执行");
                    insertData(thisNum);
                    if (finalI == 4) {
                        throw new Exception("出现异常");
                    }
                    TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(1000));
                    childResponse.add(Boolean.TRUE);
                    childMonitor.countDown();
                    System.out.println(Thread.currentThread().getName() + "：准备就绪,等待其他线程结果,判断是否事务提交");
                    mainMonitor.await();
                    if (IS_OK) {
                        System.out.println(Thread.currentThread().getName() + "：事务提交");
                        platformTransactionManager.commit(transactionStatus);
                    } else {
                        System.out.println(Thread.currentThread().getName() + "：事务回滚");
                        platformTransactionManager.rollback(transactionStatus);
                    }
                } catch (Exception e) {
                    childResponse.add(Boolean.FALSE);
                    childMonitor.countDown();
                    System.out.println(Thread.currentThread().getName() + "：出现异常,开始事务回滚");
                    if (transactionStatus != null) {
                        platformTransactionManager.rollback(transactionStatus);
                    }
                }
            });
        }
        //主线程等待所有子线程执行response
        try {
            childMonitor.await();
            for (Boolean resp : childResponse) {
                if (!resp) {
                    //如果有一个子线程执行失败了，则改变mainResult，让所有子线程回滚
                    System.out.println(Thread.currentThread().getName() + ":有线程执行失败，标志位设置为false");
                    IS_OK = false;
                    break;
                }
            }
            System.out.println("检查是否有线城失败的");
            //主线程获取结果成功，让子线程开始根据主线程的结果执行（提交或回滚）
            mainMonitor.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
